package com.neusoft.aclome.cmp.cloud.server.jcce.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.request.CloudPlatConsRequest;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.request.OnlineConsultRequest;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.CloudPlatformConsultDTO;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.ConsultGraph;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.GraphData;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.GraphLinkData;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.OnlineConsultResponse;
import com.neusoft.aclome.cmp.cloud.server.jcce.entity.CloudPlatformConsultEntity;
import com.neusoft.aclome.cmp.cloud.server.jcce.entity.ConsultProcessEntity;
import com.neusoft.aclome.cmp.cloud.server.jcce.entity.UserResourceApplyEntity;
import com.neusoft.aclome.cmp.cloud.server.jcce.repository.CloudPlatformConsultMapper;
import com.neusoft.aclome.cmp.cloud.server.jcce.repository.ConsultProcessMapper;
import com.neusoft.aclome.cmp.cloud.server.jcce.wrapper.CloudPlatformConsultWrapper;
import com.neusoft.aclome.cmp.cloud.server.model.entity.DataCenterEntity;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.entity.CloudPlatformEntity;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.repository.CloudPlatformMapper;
import com.neusoft.aclome.cmp.cloud.server.repository.database.mapper.DataCenterMapper;
import com.neusoft.aclome.cmp.cloud.server.service.DataCenterService;
import com.neusoft.aclome.cmp.cloud.server.service.OrganizationService;
import com.neusoft.aclome.cmp.common.constants.AclomeCmpOrganizationType;
import com.neusoft.aclome.cmp.common.model.vo.HttpResponse;
import com.neusoft.aclome.cmp.common.model.vo.ResponsePage;
import com.neusoft.aclome.cmp.organization.api.model.vo.ResourcePoolVO;
import com.neusoft.pub.cloud.provider.enums.ApiProviderCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

enum CloudType {
    PUBLIC, PRIVATE
}

/**
 * describe :
 *
 * @author hao.dd
 * @date 2024/2/4
 */
@Service
public class CloudPlatformConsultService {

    private static final String LOG_STRING = "2021-10-19 15:37:56,091 INFO (AclomeCMPCollectorServerApplication.java:29)- Welcome to use SaCa Aclome CMP-collector...2024-03-13 17:07:17,125 INFO (ChainedDynamicProperty.java:115)- Flipping property: aclome-cmp-organization-server.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647(BaseLoadBalancer.java:197)- Client: aclome-cmp-organization-server instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=aclome-cmp-organization-server,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null2021-10-19 15:37:56,091 INFO (AclomeCMPCollectorServerApplication.java:29)- Welcome to use SaCa Aclome CMP-collector...2024-03-13 17:07:17,125 INFO (ChainedDynamicProperty.java:115)- Flipping property: aclome-cmp-organization-server.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647(BaseLoadBalancer.java:197)- Client: aclome-cmp-organization-server instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=aclome-cmp-organization-server,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null2021-10-19 15:37:56,091 INFO (AclomeCMPCollectorServerApplication.java:29)- Welcome to use SaCa Aclome CMP-collector...2024-03-13 17:07:17,125 INFO (ChainedDynamicProperty.java:115)- Flipping property: aclome-cmp-organization-server.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647(BaseLoadBalancer.java:197)- Client: aclome-cmp-organization-server instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=aclome-cmp-organization-server,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null2021-10-19 15:37:56,091 INFO (AclomeCMPCollectorServerApplication.java:29)- Welcome to use SaCa Aclome CMP-collector...2024-03-13 17:07:17,125 INFO (ChainedDynamicProperty.java:115)- Flipping property: aclome-cmp-organization-server.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647(BaseLoadBalancer.java:197)- Client: aclome-cmp-organization-server instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=aclome-cmp-organization-server,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null2021-10-19 15:37:56,091 INFO (AclomeCMPCollectorServerApplication.java:29)- Welcome to use SaCa Aclome CMP-collector...2024-03-13 17:07:17,125 INFO (ChainedDynamicProperty.java:115)- Flipping property: aclome-cmp-organization-server.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647(BaseLoadBalancer.java:197)- Client: aclome-cmp-organization-server instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=aclome-cmp-organization-server,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null";

    private static final Logger log = LoggerFactory.getLogger(CloudPlatformConsultService.class);

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    private DataCenterService dataCenterService;

    /**
     * 公有云映射
     * map<公有云类型,公有云数量>
     */
    private static Map<String, Integer> publicPlatformIdCountMap = new HashMap<>();

    static {
        publicPlatformIdCountMap.put(ApiProviderCode.ALIYUN.name(), 100);
        publicPlatformIdCountMap.put(ApiProviderCode.TENCENT.name(), 200);
        publicPlatformIdCountMap.put(ApiProviderCode.HUAWEI.name(), 300);
        publicPlatformIdCountMap.put(ApiProviderCode.BAIDU.name(), 400);
        publicPlatformIdCountMap.put(ApiProviderCode.VOLCENGINE.name(), 500);
        publicPlatformIdCountMap.put(ApiProviderCode.CUCLOUD.name(), 600);
        publicPlatformIdCountMap.put(ApiProviderCode.SUGON.name(), 700);
    }

    /**
     * 私有云映射
     * map<私有云类型,私有云数量>
     */
    private static Map<String, Integer> privatePlatformIdCountMap = new HashMap<>();

    static {
//        privatePlatformIdCountMap.put(ApiProviderCode.ALIYUN.name(),100);
//        privatePlatformIdCountMap.put(ApiProviderCode.TENCENT.name(),200);
//        privatePlatformIdCountMap.put(ApiProviderCode.HUAWEI.name(),300);
//        privatePlatformIdCountMap.put(ApiProviderCode.BAIDU.name(),400);
//        privatePlatformIdCountMap.put(ApiProviderCode.VOLCENGINE.name(),500);
//        privatePlatformIdCountMap.put(ApiProviderCode.CUCLOUD.name(),600);
//        privatePlatformIdCountMap.put(ApiProviderCode.SUGON.name(),700);
    }

    @Value("${jcce-url.eastWestCal.consultUrl}")
    private String consultUrl;

    @Autowired
    private OrganizationService organizationService;
    /**
     * 该restTemplate 设置了超时时间
     */
    @Autowired
    private RestTemplate restTemplateTimeout;

    @Autowired
    private ConsultProcessMapper consultProcessMapper;

    @Autowired
    private CloudPlatformMapper cloudPlatformMapper;
    @Autowired
    private DataCenterMapper dataCenterMapper;

    @Autowired
    private CloudPlatformConsultMapper cloudPlatformConsultMapper;

    @Autowired
    private CloudPlatformConsultWrapper cloudPlatformConsultWrapper;

    public ResponsePage<CloudPlatformConsultDTO> pageList(CloudPlatConsRequest request) {
        PageHelper.startPage(request.getPageNumber(), request.getPageSize());
        Example example = new Example(CloudPlatformConsultEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", request.getName());
        List<CloudPlatformConsultEntity> consultEntities = cloudPlatformConsultMapper.selectByExample(example);

        List<DataCenterEntity> dataCenterEntities = dataCenterMapper.listDataCenter();
        Map<Integer, String> privatePlatformMap = dataCenterEntities.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getName()));

        PageInfo<CloudPlatformConsultEntity> pageInfo = new PageInfo<>(consultEntities);

        List<CloudPlatformEntity> cloudPlatformEntities = cloudPlatformMapper.selectAll();
        Map<Integer, String> platformIdNameMap = cloudPlatformEntities.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getPlatformName()));

        ResponsePage<CloudPlatformConsultDTO> result = new ResponsePage<>();
        result.setPage(pageInfo.getPageNum());
        result.setPages(pageInfo.getPages());
        result.setSize(pageInfo.getPageSize());
        result.setTotal(pageInfo.getTotal());
        result.setPageData(cloudPlatformConsultWrapper.toDTOListFromEntity(pageInfo.getList()).stream().peek(x -> {
            String cloudPlatformIds = x.getCloudPlatformIds();
//            String[] split = cloudPlatformIds.split(",");
            String collect = "";

            if (StringUtils.isNotBlank(cloudPlatformIds)) {
                collect = Optional.ofNullable(cloudPlatformIds)
                        .filter(y -> StringUtils.isNotBlank(y))
                        .map(ids -> Arrays.stream(ids.split(","))
                                .map(id -> platformIdNameMap.get(Integer.valueOf(id)))
                                .collect(Collectors.joining("_")))
                        .orElse("");
            }


            String privatePlatformIds = x.getPrivatePlatformIds();

            String collectPrivate = "";
            if (StringUtils.isNotBlank(privatePlatformIds)) {
                collectPrivate = Optional.ofNullable(privatePlatformIds)
                        .map(ids -> Arrays.stream(ids.split(","))
                                .map(id -> privatePlatformMap.get(Integer.valueOf(id)))
                                .collect(Collectors.joining("_")))
                        .orElse("");
            }

            StringJoiner joiner = new StringJoiner("_");
            if (StringUtils.isNotBlank(collect)) {
                joiner.add(collect);
            }
            if (StringUtils.isNotBlank(collectPrivate)) {
                joiner.add(collectPrivate);
            }
            x.setCloudPlatformNames(joiner.toString());
        }).collect(Collectors.toList()));
        return result;
    }

    public void create(CloudPlatformConsultDTO request) {
        CloudPlatformConsultEntity entity = cloudPlatformConsultWrapper.toEntityFromDTO(request, null);
        Date createdAt = new Date();
        entity.setCreatedAt(createdAt);
        entity.setUpdatedAt(createdAt);
        cloudPlatformConsultMapper.insert(entity);
    }

    public void update(CloudPlatformConsultDTO request) {
        CloudPlatformConsultEntity entity = cloudPlatformConsultWrapper.toEntityFromDTO(request, null);
        Assert.notNull(entity.getId(), "id不为空");
        CloudPlatformConsultEntity cloudPlatformConsultEntity = cloudPlatformConsultMapper.selectByPrimaryKey(entity.getId());
        Assert.notNull(cloudPlatformConsultEntity, "对应对象不为空");
        entity.setCreatedAt(cloudPlatformConsultEntity.getCreatedAt());
        entity.setUpdatedAt(new Date());
        entity.setCloudPlatformIds(cloudPlatformConsultEntity.getCloudPlatformIds());
        entity.setPrivatePlatformIds(cloudPlatformConsultEntity.getPrivatePlatformIds());
        cloudPlatformConsultMapper.updateByPrimaryKey(entity);

    }

    public void delete(Integer id) {
        cloudPlatformConsultMapper.deleteByPrimaryKey(id);
    }


    public ConsultGraph createConsult(CloudPlatformConsultDTO request) {
        // 校验
        String[] pubIds = StringUtils.isNotBlank(request.getCloudPlatformIds()) ? request.getCloudPlatformIds().split(",") : new String[]{};
        String[] privateIds = StringUtils.isNotBlank(request.getPrivatePlatformIds()) ? request.getPrivatePlatformIds().split(",") : new String[]{};

        List<Integer> selectPubIdList = Stream.of(pubIds).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
        List<Integer> selectPrivateIdList = Stream.of(privateIds).map(id -> Integer.valueOf(id)).collect(Collectors.toList());

        if ((selectPubIdList.size() + selectPrivateIdList.size()) < 2) {
            log.warn("磋商不小于2");
            throw new RuntimeException("磋商不小于2");
        }
        if (new HashSet<>(selectPubIdList).size() != selectPubIdList.size()
                && new HashSet<>(selectPrivateIdList).size() != selectPrivateIdList.size()) {
            log.warn("云商ID不可重复");
            throw new RuntimeException("云商ID不可重复");
        }

        // 全部的云商
        List<CloudPlatformEntity> allPubPlat = cloudPlatformMapper.selectAll();
        List<DataCenterEntity> allPravitePlat = dataCenterMapper.listDataCenter();

        List<ResourcePoolVO> privateDataCenters = organizationService.listResourcePoolByType(AclomeCmpOrganizationType.DATA_CENTER).getData();
        // 收集公有云id映射map
        Map<Integer, ResourcePoolVO> privateIdMap = privateDataCenters.stream().collect(Collectors.toMap(x -> x.getDataCenterId(), Function.identity(), (u, v) -> v, HashMap::new));

        List<Integer> platPubIds = allPubPlat.stream().map(e -> e.getId()).collect(Collectors.toList());
        List<Integer> platPrivateIds = allPravitePlat.stream().map(e -> e.getId()).collect(Collectors.toList());

        if (!selectPubIdList.stream().allMatch(p -> platPubIds.contains(p))
                || !selectPrivateIdList.stream().allMatch(p -> platPrivateIds.contains(p))) {
            log.warn("云商ID不存在");
            throw new RuntimeException("云商ID不存在");
        }
        // 校验结束

        //选择的公有云,私有云
        List<CloudPlatformEntity> selectPubPlat = allPubPlat.stream().filter(a -> selectPubIdList.contains(a.getId())).collect(Collectors.toList());

        // 收集公有云id映射map
        Map<Integer, CloudPlatformEntity> pubIdMap = selectPubPlat.stream().collect(Collectors.toMap(x -> x.getId(), Function.identity()));

        List<DataCenterEntity> selectPrivatePlat = allPravitePlat.stream().filter(a -> selectPrivateIdList.contains(a.getId())).collect(Collectors.toList());

        log.info("输入公有云:" + selectPubPlat.stream().map(CloudPlatformEntity::getId).collect(Collectors.toList()));
        log.info("输入私有云:" + selectPrivatePlat.stream().map(DataCenterEntity::getId).collect(Collectors.toList()));

        // ------------------校验结束
        // 划线，逻辑：将选择云商画个圈围起来
        ConsultGraph result = new ConsultGraph();
        List<GraphLinkData> graphLinkDataList = new ArrayList<>();

        List<ConsultEntity> reqList = new ArrayList<>();
        generateConsultRequest(selectPubIdList, selectPrivateIdList, privateIdMap, pubIdMap, reqList);

        // 调用磋商方法
        List<List<ConsultEntity>> consultedList = consult(reqList);

        int count = 1;
        int count2 = 1;

        // 绘制图信息
        drawGraph(allPubPlat, allPravitePlat, result, graphLinkDataList, reqList, consultedList, count, count2);
        // 删除历史磋商
        deleteHistoryConsult();
        // 构建保存数据库
        executeInsertConsult(allPubPlat, allPravitePlat, consultedList);

        // 增加其他未磋商的云商，为了构建图
        allPubPlat.forEach(pub -> {
            if (!selectPubIdList.contains(pub.getId())) {
                result.getGraphDataList().add(new GraphData(null, pub.getPlatformName(), 0, pub.getId(), null));
            }
        });
        allPravitePlat.forEach(priv -> {
            if (!selectPrivateIdList.contains(priv.getId())) {
                result.getGraphDataList().add(new GraphData(null, priv.getName(), 0, priv.getId(), null));
            }
        });

        // 线
        result.setGraphLinkDataList(graphLinkDataList);

        try {
            // 保存到磋商任务中
            ConsultProcessEntity consultProcessEntity = new ConsultProcessEntity();

            List<String> buildNames = new ArrayList<>();
            StringBuffer buildName = new StringBuffer();
            selectPubPlat.stream().map(CloudPlatformEntity::getPlatformName).forEach(buildNames::add);
            selectPrivatePlat.stream().map(DataCenterEntity::getName).forEach(buildNames::add);

            for (int i = 0; i < buildNames.size() && i < 3; i++) {
                if (i != 0) {
                    buildName.append(",");
                }
                buildName.append(buildNames.get(i));
            }
            if (buildNames.size() > 3) {
                buildName.append("等");
            }
            buildName.append("的磋商任务");
            consultProcessEntity.setName(buildName.toString());
            consultProcessEntity.setPubCloudIds(request.getCloudPlatformIds());
            consultProcessEntity.setPrivCloudIds(request.getPrivatePlatformIds());
            consultProcessEntity.setStartTime(new Date());
            consultProcessEntity.setLogInfo(LOG_STRING);
            consultProcessEntity.setPercentage(new BigDecimal(0));
            consultProcessEntity.setProfitDistribution(0);
            consultProcessEntity.setResourcePricing(0);
            consultProcessEntity.setCloudFeedback(0);
            consultProcessEntity.setMonitoringGovernance(0);
            consultProcessMapper.insert(consultProcessEntity);
            // 通知武大课题3
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    private void generateConsultRequest(List<Integer> selectPubIdList, List<Integer> selectPrivateIdList, Map<Integer, ResourcePoolVO> privateIdMap, Map<Integer, CloudPlatformEntity> pubIdMap, List<ConsultEntity> reqList) {
        selectPubIdList.forEach(p -> {
            ConsultEntity consultEntity = new ConsultEntity();
            CloudPlatformEntity cloudPlatformEntity = pubIdMap.get(p);
            consultEntity.setPubCpuQuota(0);
            consultEntity.setPubMemoryQuota(0);
            consultEntity.setPubCapacityQuota(cloudPlatformEntity.getCapacityQuota());
            consultEntity.setPubBandwidthQuota(0);
            consultEntity.setPrivCpuQuota(0);
            consultEntity.setPrivMemoryQuota(0);
            consultEntity.setPrivCapacityQuota(0);
            consultEntity.setType(CloudType.PUBLIC);
            consultEntity.setId(p);
            consultEntity.setName(cloudPlatformEntity.getPlatformName());
            reqList.add(consultEntity);
        });
        selectPrivateIdList.forEach(p -> {
            ResourcePoolVO resourcePoolVO = privateIdMap.get(p);
            ConsultEntity consultEntity = new ConsultEntity();
            consultEntity.setPubCpuQuota(0);
            consultEntity.setPubMemoryQuota(0);
            consultEntity.setPubCapacityQuota(0);
            consultEntity.setPubBandwidthQuota(0);
            consultEntity.setPrivCpuQuota(resourcePoolVO.getVcpus());//
            double v = new BigDecimal(resourcePoolVO.getMem()).divide(BigDecimal.valueOf(1073741824), 0, RoundingMode.DOWN).doubleValue();
            consultEntity.setPrivMemoryQuota((int) v);
            double v2 = new BigDecimal(resourcePoolVO.getStorage()).divide(BigDecimal.valueOf(1073741824), 0, RoundingMode.DOWN).doubleValue();
            consultEntity.setPrivCapacityQuota((int) v2);
            consultEntity.setType(CloudType.PRIVATE);
            consultEntity.setId(p);
            consultEntity.setName(resourcePoolVO.getName());
            reqList.add(consultEntity);
        });
    }

    private void drawGraph(List<CloudPlatformEntity> allPubPlat, List<DataCenterEntity> allPravitePlat, ConsultGraph result, List<GraphLinkData> graphLinkDataList, List<ConsultEntity> reqList, List<List<ConsultEntity>> consultedList, int count, int count2) {
        for (int i = 0; i < consultedList.size(); i++) {
            List<ConsultEntity> l = consultedList.get(i);
            List<GraphData> dataList = new ArrayList<>();
            for (int j = 0; j < l.size(); j++) {
                ConsultEntity e = consultedList.get(i).get(j);
                // 数据
                dataList.add(new GraphData(count, getName(e, allPubPlat, allPravitePlat), 0, e.getId(), null));
                // 划线
                if (j == (l.size() - 1)) {
                    graphLinkDataList.add(new GraphLinkData(count, (count - (l.size() - 1))));
                } else {
                    graphLinkDataList.add(new GraphLinkData(count, (count + 1)));
                }
                count++;
            }
            if (dataList.size() == 1) {
                result.getGraphDataList().add(dataList.get(0));
            } else {
                GraphData d = new GraphData(reqList.size() + count2, getNames(dataList), 0, null, dataList);
                result.getGraphDataList().add(d);
                count2++;
            }
        }
    }

    private void executeInsertConsult(List<CloudPlatformEntity> allPubPlat, List<DataCenterEntity> allPravitePlat, List<List<ConsultEntity>> consultedList) {
        for (List<ConsultEntity> d : consultedList) {
            // 每个d是一个磋商的新云商
            // ids为新云商包含的原云商CloudPlatformId列表
            CloudPlatformConsultDTO entity = new CloudPlatformConsultDTO();

            List<String> pubIdL2 = d.stream().filter(e -> CloudType.PUBLIC.equals(e.getType())).map(c -> String.valueOf(c.getId())).collect(Collectors.toList());
            List<String> privateId2 = d.stream().filter(e -> CloudType.PRIVATE.equals(e.getType())).map(c -> String.valueOf(c.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(pubIdL2)) {
                entity.setCloudPlatformIds(String.join(",", pubIdL2));
            }
            if (CollectionUtils.isNotEmpty(privateId2)) {
                entity.setPrivatePlatformIds(String.join(",", privateId2));
            }

            if (d.size() != 1) {
                entity.setRemark(getName(d.get(0), allPubPlat, allPravitePlat) + "等" + d.size() + "个云商于" + sdf.format(new Date()) + "磋商后产生的云际服务提供者");
                entity.setName(getNames(d, allPubPlat, allPravitePlat));
            } else {
                String name = getName(d.get(0), allPubPlat, allPravitePlat);
                entity.setRemark(name + "于" + sdf.format(new Date()) + "磋商后变更为独立云际服务提供者");
                entity.setName(name);
            }

            create(entity);
            System.out.println("磋商结果：" + JSONObject.toJSONString(entity));
        }
    }

    private void deleteHistoryConsult() {
        cloudPlatformConsultMapper.deleteByExample(new Example(CloudPlatformConsultEntity.class));
    }


    private String getNames(List<ConsultEntity> list, List<CloudPlatformEntity> pubList, List<DataCenterEntity> privateList) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            ConsultEntity e = list.get(i);
            if (i != 0) {
                sb.append("+");
            }
            sb.append(getName(e, pubList, privateList));
        }
        return sb.toString();
    }

    private String getName(ConsultEntity entity, List<CloudPlatformEntity> pubList, List<DataCenterEntity> privateList) {
        if (CloudType.PRIVATE.equals(entity.getType())) {
            for (DataCenterEntity p : privateList) {
                if (p.getId().equals(entity.getId())) {
                    return p.getName();
                }
            }
        }
        if (CloudType.PUBLIC.equals(entity.getType())) {
            for (CloudPlatformEntity p : pubList) {
                if (p.getId().equals(entity.getId())) {
                    return p.getPlatformName();
                }
            }
        }
        return "";
    }

    private String getNames(List<GraphData> list) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            String e = list.get(i).getName();
            if (i != 0) {
                sb.append("+");
            }
            sb.append(e);
        }
        return sb.toString();
    }

    // 磋商逻辑，可以在此处写死，包括后续增加公有云私有云校验
    private List<List<ConsultEntity>> consult(List<ConsultEntity> list) {
        List<List<ConsultEntity>> res = new ArrayList<>();

        // 公有云私有云分组
        List<ConsultEntity> pubList = list.stream().filter(l -> CloudType.PUBLIC.equals(l.getType())).collect(Collectors.toList());
        List<ConsultEntity> privateList = list.stream().filter(l -> CloudType.PRIVATE.equals(l.getType())).collect(Collectors.toList());
        try {

            executeOnlineConsult(pubList, privateList, res);
        } catch (Exception e) {
            log.error("执行线上磋商失败，改用本地磋商实现", e);
            //公有云私有云分开磋商
            consultGroup(res, pubList);
            consultGroup(res, privateList);
        }

        return res;
    }

    /**
     * 在线磋商
     *
     * @param pubList
     * @param privateList
     * @param res
     */
    private void executeOnlineConsult(List<ConsultEntity> pubList,
                                      List<ConsultEntity> privateList,
                                      List<List<ConsultEntity>> res) {
        // 定义map映射信息
        pubList.stream().collect(Collectors.toMap(x -> x.getId(), Function.identity(), (u, v) -> v, HashMap::new));

        OnlineConsultRequest request = new OnlineConsultRequest();
        request.setPrivPlatformList(privateList.stream().map(x -> {
            OnlineConsultRequest.Platform platform = new OnlineConsultRequest.Platform();
            platform.setName(x.getName());
            platform.setPubCpuQuota(x.getPubCpuQuota());
            platform.setPubMemoryQuota(x.getPubMemoryQuota());
            platform.setPubCapacityQuota(x.getPubCapacityQuota());
            platform.setPubBandwidthQuota(x.getPubBandwidthQuota());
            platform.setPrivCpuQuota(x.getPrivCpuQuota());
            platform.setPrivMemoryQuota(x.getPrivMemoryQuota());
            platform.setPrivCapacityQuota(x.getPrivCapacityQuota());

            platform.setId(x.getId());
            platform.setType(x.getType().name());
            return platform;
        }).collect(Collectors.toList()));

        request.setPubPlatformList(pubList.stream().map(x -> {
            OnlineConsultRequest.Platform platform = new OnlineConsultRequest.Platform();
            platform.setName(x.getName());
            platform.setPubCpuQuota(x.getPubCpuQuota());
            platform.setPubMemoryQuota(x.getPubMemoryQuota());
            platform.setPubCapacityQuota(x.getPubCapacityQuota());
            platform.setPubBandwidthQuota(x.getPubBandwidthQuota());
            platform.setPrivCpuQuota(x.getPrivCpuQuota());
            platform.setPrivMemoryQuota(x.getPrivMemoryQuota());
            platform.setPrivCapacityQuota(x.getPrivCapacityQuota());

            platform.setId(x.getId());
            platform.setType(x.getType().name());
            return platform;
        }).collect(Collectors.toList()));

        log.info("调用东数西算接口磋商，请求参数如下{}", JSON.toJSONString(request));
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity<HttpResponse<OnlineConsultResponse>> exchange = restTemplateTimeout.exchange(consultUrl, HttpMethod.POST,
                new HttpEntity<>(request), new ParameterizedTypeReference<HttpResponse<OnlineConsultResponse>>() {
                });
        log.info("调用东数西算接口磋商，请求参数如下{}", JSON.toJSONString(exchange.getBody()));
        if (Objects.requireNonNull(exchange.getBody()).getCode() != 200) {
            throw new IllegalArgumentException("调用在线磋商失败");
        }
        List<OnlineConsultResponse.Consult> privPlatformConsultList = exchange.getBody().getData().getPrivPlatformConsultList();
        List<OnlineConsultResponse.Consult> pubPlatformConsultList = exchange.getBody().getData().getPubPlatformConsultList();

        privPlatformConsultList.forEach(consult -> {
            String consultName = consult.getConsultName();//TODO 磋商名称 需要更改原逻辑
            List<ConsultEntity> collect = consult.getConsultIds().stream().map(x -> new ConsultEntity(CloudType.PRIVATE, x)).collect(Collectors.toList());
            res.add(collect);
        });

        pubPlatformConsultList.forEach(consult -> {
            List<ConsultEntity> collect = consult.getConsultIds().stream().map(x -> new ConsultEntity(CloudType.PUBLIC, x)).collect(Collectors.toList());
            res.add(collect);
        });
    }

    // 磋商分组逻辑
    private void consultGroup(List<List<ConsultEntity>> res, List<ConsultEntity> consultList) {
        switch (consultList.size()) {
            case 1:
            case 2:
                res.add(consultList);
                break;
            case 3:
                //0-1,2
                res.add(consultList.subList(0, 2));
                res.add(consultList.subList(2, 3));
                break;
            case 4:
                //0-2,3
                res.add(consultList.subList(0, 3));
                res.add(consultList.subList(3, 4));
                break;
            case 5:
                //0-2,3-4
                res.add(consultList.subList(0, 3));
                res.add(consultList.subList(3, 5));
                break;
            case 6:
                //0-2,3-4,5
                res.add(consultList.subList(0, 3));
                res.add(consultList.subList(3, 5));
                res.add(consultList.subList(5, 6));
                break;
            case 0:
            default:
                break;
        }
    }

    public List<Integer> getConsultResourceCount(String cloudType, Integer id) {
        ArrayList<Integer> integers = new ArrayList<>();
        List<CloudPlatformConsultEntity> consultEntityList = cloudPlatformConsultMapper.selectAll();
        if ("public".equals(cloudType)) {
            CloudPlatformEntity cloudPlatformEntity = cloudPlatformMapper.selectByPrimaryKey(id);
            Integer startSum = publicPlatformIdCountMap.get(cloudPlatformEntity.getApiProvider());
            List<CloudPlatformEntity> cloudPlatformEntities = cloudPlatformMapper.selectAll();
            Map<Integer, CloudPlatformEntity> cloudPrlatformIdMap = cloudPlatformEntities.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));

            CloudPlatformConsultEntity cloudPlatformConsultEntity = consultEntityList.stream()
                    .filter(x->StringUtils.isNotBlank(x.getCloudPlatformIds()))
                    .filter(x -> Arrays.asList(x.getCloudPlatformIds().split(",")).contains(String.valueOf(cloudPlatformEntity.getId())))
                    .findFirst().orElse(null);

            int endSum =  0;

            if (cloudPlatformConsultEntity == null) {
                // 没有磋商记录，就设置成xxx
                integers.add(startSum);
                integers.add(startSum);

                // 新增配额
                integers.add(cloudPlatformEntity.getCpuQuota());
                integers.add(cloudPlatformEntity.getCpuQuota());
                integers.add(cloudPlatformEntity.getMemQuota());
                integers.add(cloudPlatformEntity.getMemQuota());
            } else {
                endSum = Arrays.asList(cloudPlatformConsultEntity.getCloudPlatformIds().split(","))
                        .stream().mapToInt(x -> publicPlatformIdCountMap.get(cloudPrlatformIdMap.get(Integer.valueOf(x)).getApiProvider())).sum();
                int cpuSum = Arrays.asList(cloudPlatformConsultEntity.getCloudPlatformIds().split(","))
                        .stream().mapToInt(x -> cloudPrlatformIdMap.get(Integer.valueOf(x)).getCpuQuota()).sum();
                int memSum = Arrays.asList(cloudPlatformConsultEntity.getCloudPlatformIds().split(","))
                        .stream().mapToInt(x -> cloudPrlatformIdMap.get(Integer.valueOf(x)).getMemQuota()).sum();
                integers.add(startSum);
                integers.add(endSum);
                integers.add(cloudPlatformEntity.getCpuQuota());
                integers.add(cpuSum);
                integers.add(cloudPlatformEntity.getMemQuota());
                integers.add(memSum);
            }
        } else {
            // 磋商的私有云
            CloudPlatformConsultEntity cloudPlatformConsultEntity = consultEntityList.stream()
                    .filter(x->StringUtils.isNotBlank(x.getPrivatePlatformIds()))
                    .filter(x -> Arrays.asList(x.getPrivatePlatformIds().split(",")).contains(String.valueOf(id)))
                    .findFirst().orElse(new CloudPlatformConsultEntity());
            integers.add(100);
            integers.add(Optional.ofNullable(cloudPlatformConsultEntity.getPrivatePlatformIds()).map(x->x.split(",").length).orElse(1) * 100);

            // 私有云配额，以云商ID为key
            List<DataCenterEntity> privateList = dataCenterService.listDataCenter(false, false, false);
            Map<Integer, ResourcePoolVO> privateIdMap = organizationService.listResourcePoolByType(AclomeCmpOrganizationType.DATA_CENTER)
                    .getData().stream().collect(Collectors.toMap(x -> x.getDataCenterId(), Function.identity(), (u, v) -> v, HashMap::new));

            int cpu = privateIdMap.keySet().stream().filter(idd -> idd.equals(id)).mapToInt(k -> privateIdMap.get(k).getVcpus()).sum();
            int mem = (int)privateIdMap.keySet().stream().filter(idd -> idd.equals(id)).mapToLong(k -> privateIdMap.get(k).getMem() / 1024 / 1024 / 1024).sum();

            int cpuTotal = privateIdMap.keySet().stream()
                    .filter(idd -> Arrays.asList(cloudPlatformConsultEntity.getPrivatePlatformIds().split(",")).contains(String.valueOf(idd)))
                    .mapToInt(k -> privateIdMap.get(k).getVcpus()).sum();
            int memTotal = (int)privateIdMap.keySet().stream()
                    .filter(idd -> Arrays.asList(cloudPlatformConsultEntity.getPrivatePlatformIds().split(",")).contains(String.valueOf(idd)))
                    .mapToLong(k -> privateIdMap.get(k).getMem() / 1024 / 1024 / 1024).sum();

            integers.add(cpu);
            integers.add(cpuTotal);
            integers.add(mem);
            integers.add(memTotal);
        }
        return integers;
    }
}

class ConsultEntity {

    private CloudType type;

    private String name;

    private int id;

    // 公有云 CPU 配额，单位 GB
    private Integer pubCpuQuota;
    // 公有云内存配额，单位 GB
    private Integer pubMemoryQuota;
    // 公有云存储配额，单位 GB
    private Integer pubCapacityQuota;
    // 公有云带宽配额，单位 MB/s
    private Integer pubBandwidthQuota;
    // 私有云 CPU 配额，单位 GB
    private Integer privCpuQuota;
    // 私有云内存配额，单位 GB
    private Integer privMemoryQuota;
    // 私有云存储配额，单位 GB
    private Integer privCapacityQuota;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ConsultEntity() {
    }

    public ConsultEntity(CloudType type, int id) {
        this.type = type;
        this.id = id;
    }


    public Integer getPubCpuQuota() {
        return pubCpuQuota;
    }

    public void setPubCpuQuota(Integer pubCpuQuota) {
        this.pubCpuQuota = pubCpuQuota;
    }

    public Integer getPubMemoryQuota() {
        return pubMemoryQuota;
    }

    public void setPubMemoryQuota(Integer pubMemoryQuota) {
        this.pubMemoryQuota = pubMemoryQuota;
    }

    public Integer getPubCapacityQuota() {
        return pubCapacityQuota;
    }

    public void setPubCapacityQuota(Integer pubCapacityQuota) {
        this.pubCapacityQuota = pubCapacityQuota;
    }

    public Integer getPubBandwidthQuota() {
        return pubBandwidthQuota;
    }

    public void setPubBandwidthQuota(Integer pubBandwidthQuota) {
        this.pubBandwidthQuota = pubBandwidthQuota;
    }

    public Integer getPrivCpuQuota() {
        return privCpuQuota;
    }

    public void setPrivCpuQuota(Integer privCpuQuota) {
        this.privCpuQuota = privCpuQuota;
    }

    public Integer getPrivMemoryQuota() {
        return privMemoryQuota;
    }

    public void setPrivMemoryQuota(Integer privMemoryQuota) {
        this.privMemoryQuota = privMemoryQuota;
    }

    public Integer getPrivCapacityQuota() {
        return privCapacityQuota;
    }

    public void setPrivCapacityQuota(Integer privCapacityQuota) {
        this.privCapacityQuota = privCapacityQuota;
    }

    public CloudType getType() {
        return type;
    }

    public void setType(CloudType type) {
        this.type = type;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}